<script src="../../dist/mini-vue.js"></script>

<!-- DemoGrid component template -->
<script type="text/x-template" id="grid-template">
    <table v-if="filteredData.value.length">
    <thead>
      <tr>
        <th v-for="key in columns"
          @click="sortBy(key)"
          :class="state.sortKey == key ? 'active' : ''">
          {{ capitalize(key) }}
          <span :class="'arrow ' + (state.sortOrders[key] > 0 ? 'asc' : 'dsc')">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="entry in filteredData.value">
        <td v-for="key in columns">
          {{entry[key]}}
        </td>
      </tr>
    </tbody>
  </table>
  <p v-else>No matches found.</p>
</script>
<!-- DemoGrid component script -->
<script>
    const { reactive, computed, ref } = MiniVue;

    const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);

    const DemoGrid = {
        template: '#grid-template',
        props: ['data', 'columns', 'filterKey'],
        setup(props) {
            const state = reactive({
                sortKey: '',
                sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),
            });

            const filteredData = computed(() => {
                let { data, filterKey } = props;
                if (filterKey) {
                    filterKey = filterKey.toLowerCase();
                    data = data.filter((row) => {
                        return Object.keys(row).some((key) => {
                            return String(row[key]).toLowerCase().indexOf(filterKey) > -1;
                        });
                    });
                }
                const { sortKey } = state;
                if (sortKey) {
                    const order = state.sortOrders[sortKey];
                    data = data.slice().sort((a, b) => {
                        a = a[sortKey];
                        b = b[sortKey];
                        return (a === b ? 0 : a > b ? 1 : -1) * order;
                    });
                }
                return data;
            });

            function sortBy(key) {
                state.sortKey = key;
                state.sortOrders[key] *= -1;
            }

            return {
                state,
                filteredData,
                sortBy,
                capitalize,
            };
        },
    };
</script>

<!-- App template (in DOM) -->
<div id="demo">
    <form id="search">
        Search <input name="query" v-model="searchQuery.value" />
    </form>
    <demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery.value">
    </demo-grid>
</div>
<!-- App script -->
<script>
    MiniVue.createApp({
        components: {
            DemoGrid,
        },
        setup() {
            return {
                // 不同于原版，这里需要用ref
                // 可能是因为v-model机制不同，原版修改的是经过props响应化后的响应式对象，
                // 而这里修改的是普通值，因此要显示定义为ref
                searchQuery: ref(''),
                gridColumns: ['name', 'power'],
                gridData: [
                    {
                        name: 'Chuck Norris',
                        power: Infinity,
                    },
                    {
                        name: 'Bruce Lee',
                        power: 9000,
                    },
                    {
                        name: 'Jackie Chan',
                        power: 7000,
                    },
                    {
                        name: 'Jet Li',
                        power: 8000,
                    },
                ],
            };
        },
    }).mount('#demo');
</script>

<style>
    body {
        font-family: Helvetica Neue, Arial, sans-serif;
        font-size: 14px;
        color: #444;
    }

    table {
        border: 2px solid #42b983;
        border-radius: 3px;
        background-color: #fff;
    }

    th {
        background-color: #42b983;
        color: rgba(255, 255, 255, 0.66);
        cursor: pointer;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
    }

    td {
        background-color: #f9f9f9;
    }

    th,
    td {
        min-width: 120px;
        padding: 10px 20px;
    }

    th.active {
        color: #fff;
    }

    th.active .arrow {
        opacity: 1;
    }

    .arrow {
        display: inline-block;
        vertical-align: middle;
        width: 0;
        height: 0;
        margin-left: 5px;
        opacity: 0.66;
    }

    .arrow.asc {
        border-left: 4px solid transparent;
        border-right: 4px solid transparent;
        border-bottom: 4px solid #fff;
    }

    .arrow.dsc {
        border-left: 4px solid transparent;
        border-right: 4px solid transparent;
        border-top: 4px solid #fff;
    }
</style>